package common;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class WordSpaceSavingAlgorithm implements Serializable {

    private Map<String, WordFrequency> topWords;

    private List<WordFrequency> wordsSortedByFreq;

    private final int maxSpace;

    public WordSpaceSavingAlgorithm(int maxSpace) {
        this.maxSpace = maxSpace;
        topWords = new HashMap<String, WordFrequency>(maxSpace);
        wordsSortedByFreq = new LinkedList<WordFrequency>();
    }

    public void processNewWord(String word) {
        if (topWords.containsKey(word)) {
            topWords.get(word).incrementCount();
            Collections.sort(wordsSortedByFreq);
        } else if (topWords.size() < maxSpace) {
            final WordFrequency newWord = new WordFrequency(word);
            topWords.put(word, newWord);
            wordsSortedByFreq.add(newWord);
            Collections.sort(wordsSortedByFreq);
        } else {
            final WordFrequency wordToRemove = wordsSortedByFreq.get(0);

            topWords.remove(word);
            wordsSortedByFreq.remove(0);

            final WordFrequency newWord = new WordFrequency(word, wordToRemove.getCount(), wordToRemove.getTweetCount());
            newWord.incrementCount();

            topWords.put(word, newWord);
            wordsSortedByFreq.add(newWord);
            Collections.sort(wordsSortedByFreq);
        }
    }

    public List<WordFrequency> getTopItems(int count) {
        final List<WordFrequency> result = new ArrayList<WordFrequency>();

        if (wordsSortedByFreq.size() <= count) {
            for (final WordFrequency wf : wordsSortedByFreq) {
                result.add(new WordFrequency(wf.getWord(), wf.getCount(), wf.getTweetCount()));
                Collections.reverse(result);
            }
        } else {
            for (int i = 1; i <= count; i++) {
                final WordFrequency wf = wordsSortedByFreq.get(wordsSortedByFreq.size() - i);
                result.add(new WordFrequency(wf.getWord(), wf.getCount(), wf.getTweetCount()));
            }
        }

        return result;
    }

    public void incrementTweetCount(String word) {
        if (topWords.containsKey(word)) {
            topWords.get(word).incrementTweetCount();
        }
    }

    public void reset() {
        topWords.clear();
        wordsSortedByFreq.clear();
    }
}
